package day12;

/**
 * 虽然能解决线程安全的问题，但是希望只唤醒对方线程而不唤醒本方线程
 * @author wangbiao
 *
 */
public class ProducerConsumerDemo {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		CommonResource resource = new CommonResource();
		new Thread(new Producer(resource)).start();
		new Thread(new Producer(resource)).start();
		new Thread(new Consumer(resource)).start();
		new Thread(new Consumer(resource)).start();
	}

}

class CommonResource {

	private String name;

	private int count = 0;

	private boolean flag = false;

	public synchronized void setValue(String name) {
		// 循环判断标记，会导致所有线程都等待。因此不能只唤醒当前等待的第一个线程，要唤醒所有的等待的线程
		while (flag) {
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		this.name = name + "..." + this.count++;
		System.out.println(Thread.currentThread().getName() + "..." + "生产者"
				+ this.name);
		this.flag = true;
		this.notifyAll();
	}

	public synchronized void outValue() {
		while (!flag) {
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println(Thread.currentThread().getName() + "......" + "消费者"
				+ this.name);
		this.flag = false;
		this.notifyAll();// 唤醒本方和对方
	}
}

class Producer implements Runnable {

	private CommonResource resource;

	public Producer(CommonResource resource) {
		this.resource = resource;
	}

	@Override
	public void run() {
		while (true) {
			this.resource.setValue("+商品+");
		}
	}

}

class Consumer implements Runnable {

	private CommonResource resource;

	public Consumer(CommonResource resource) {
		this.resource = resource;
	}

	@Override
	public void run() {
		while (true) {
			this.resource.outValue();
		}
		
	}

}